/*
# File    :   spi.c
# Author  :   SCHIPS
# Mail    :   schips@dingtalk.com
# Date    :   Tue, Apr 30, 2019  4:04:21 PM
# Note    :   SPI with R/W SD card demo based on C51
*/

#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#include <9325TP.h>

#include "spi.h"
//============================================================
//检测SD卡的响应
unsigned char SdResponse()
{
    unsigned char i = 0,response;

    while(i <= 8)
    {
        response = SPIRead();
        if(response == 0x00)
            break;
        if(response == 0x01)
            break;
        i++;
    }
    return response;
}

//================================================================
//发命令到SD卡
void SdCommand(unsigned char command, unsigned long argument, unsigned char CRC)
{
    SPIWrite(command| 0x40);
    SPIWrite(((unsigned char *)&argument)[0]);
    SPIWrite(((unsigned char *)&argument)[1]);
    SPIWrite(((unsigned char *)&argument)[2]);
    SPIWrite(((unsigned char *)&argument)[3]);
    SPIWrite(CRC);
}
//================================================================
//
//================================================================
//初始化SD卡
unsigned char SdInit(void)
{
    int delay = 0, trials = 0;
    unsigned char i;
    unsigned char response = 0x01;

    SPI_CS = 1;
    for(i = 0;i <= 9;i++)
    SPIWrite(0xff);
    SPI_CS = 0;

    //Send Command 0 to put MMC in SPI mode
    SdCommand(0x00, 0, 0x95);

    response=SdResponse();

    if(response != 0x01)
    {
        return 0;
    }

    while(response == 0x01)
    {
        SPI_CS = 1;
        SPIWrite(0xff);
        SPI_CS = 0;
        SdCommand(0x01,0x00ffc000,0xff);
        response = SdResponse();
    }

    SPI_CS = 1;
    SPIWrite(0xff);
    return 1;
}
//================================================================
//往SD卡指定地址写数据,一次最多512字节
unsigned char SdWriteBlock(unsigned char *Block, unsigned long address,int len)
{
    unsigned int count;
    unsigned char dataResp;
    //Block size is 512 bytes exactly
    //First Lower SS

    SPI_CS=0;
    //Then send write command
    SdCommand(0x18,address,0xff);

    if(SdResponse()==00)
    {
        SPIWrite(0xff);
        SPIWrite(0xff);
        SPIWrite(0xff);
        //command was a success - now send data
        //start with DATA TOKEN = 0xFE
        SPIWrite(0xfe);
        //now send data
        for(count=0;count<len;count++) SPIWrite(*Block++);

        for(;count<512;count++) SPIWrite(0);
        //data block sent - now send checksum
        SPIWrite(0xff); //两字节CRC校验, 为0XFFFF 表示不考虑CRC
        SPIWrite(0xff);
        //Now read in the DATA RESPONSE token
        dataResp=SPIRead();
        //Following the DATA RESPONSE token
        //are a number of BUSY bytes
        //a zero byte indicates the MMC is busy

        while(SPIRead()==0);

        dataResp=dataResp&0x0f; //mask the high byte of the DATA RESPONSE token
        SPI_CS=1;
        SPIWrite(0xff);
        if(dataResp==0x0b)
        {
        //printf("DATA WAS NOT ACCEPTED BY CARD -- CRC ERROR\n");
           return 0;
        }
        if(dataResp==0x05)
            return 1;

        //printf("Invalid data Response token.\n");
        return 0;
    }
//printf("Command 0x18 (Write) was not received by the MMC.\n");
return 0;
}

//=======================================================================
//从SD卡指定地址读取数据,一次最多512字节
unsigned char SdReadBlock(unsigned char *Block, unsigned long address,int len)
{

    unsigned int count;
    //Block size is 512 bytes exactly
    //First Lower SS

     //printf("MMC_read_block\n");

    SPI_CS=0;
    //Then send write command
    SdCommand(0x11,address,0xff);

    if(SdResponse()==00)
    {
        //command was a success - now send data
        //start with DATA TOKEN = 0xFE
        while(SPIRead()!=0xfe);

        for(count=0;count<len;count++) *Block++=SPIRead();

        for(;count<512;count++) SPIRead();

        //data block sent - now send checksum
        SPIRead();
        SPIRead();
        //Now read in the DATA RESPONSE token
        SPI_CS=1;
        SPIRead();
        return 1;
    }
     //printf("Command 0x11 (Read) was not received by the MMC.\n");
    return 0;
}

void Com_Init(void)
{
     TMOD = 0x20;
     PCON = 0x00;
     SCON = 0x50;   
     TH1 = 0xFd;
     TL1 = 0xFd;
     TR1 = 1;   
}

